package entities;

import items.ItemBlock;
import main.Map;

import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.SlickException;

import shared.Timer;

import blocks.Block;

public class NPC extends WorldEntity {
	//Physics
	private int speed;
	private int maxFallSpeed;
	private int currentFallSpeed;
	private int fallSpeedIncrement;
	private int jumpPower;
	private boolean isJumping;
	private int playerPosX;
	private int playerPosY;
	private int damage;
	private float knockbackTime;
	private Timer attackTimer;
	private float attackSpeed;
	private boolean isAlive;
	
	//Graphics
	private Image texture;
	
	
	public NPC(int x, int y, int width, int height) throws SlickException {
		super(x, y, width, height);
		
		speed = 2;
		maxFallSpeed = 25;
		currentFallSpeed = 0;
		fallSpeedIncrement = 1;
		setHealth(10);
		texture = new Image("resources/entities/enemy_default.png");
		playerPosX = 0;
		playerPosY = 0;
		jumpPower = 20;
		isJumping = false;
		damage = 10;
		knockbackTime = 0.1f;
		attackSpeed = 1.0f;
		attackTimer = new Timer(attackSpeed);
		isAlive = true;
	}
	

	public void update(Player player) throws SlickException {
		updatePlayerPositions(player.getX() + player.getWidth()/2, player.getY() + player.getHeight()/2);
		fall();
		if(!checkPlayerCollision(player)) {
			move();
		} else {
			if(attackTimer.update()) {
				if(getX() < player.getX()) {
					player.getHit(damage, 1, knockbackTime);
				} else {
					player.getHit(damage, -1, knockbackTime);
				}
				attackTimer.resetTimer();
			}
		}
		updatePolygon();
	}
	
	private boolean checkPlayerCollision(Player player) {
		if(player.getPolygon().intersects(getPolygon()) || player.getPolygon().contains(getPolygon()) || getPolygon().contains(player.getPolygon())) {
			return true;
		} else {
			return false;
		}
	}


	private void move() {
		if(getX() < playerPosX) {
			if(!collidedWithBlock(speed, 0)) {
				setX(getX() + speed);
			} else {
				if(!isJumping) {
					currentFallSpeed = -jumpPower;
					isJumping = true;
				}
			}
		} else {
			if(!collidedWithBlock(-speed, 0)) {
				setX(getX() - speed);
			} else {
				if(!isJumping) {
					currentFallSpeed = -jumpPower;
					isJumping = true;
				}
			}
		}
	}


	private void updatePlayerPositions(int x, int y) {
		playerPosX = x;
		playerPosY = y;
	}


	private void fall() {
		if(currentFallSpeed < maxFallSpeed) {
			currentFallSpeed += fallSpeedIncrement;
		}
		
		if(!collidedWithBlock(0, currentFallSpeed)) {
			setY(getY() + currentFallSpeed);
		} else {
			currentFallSpeed = 0;
			isJumping = false;
		}
	}
	
	public void getHit(int damage) throws SlickException {
		setHealth(getHealth() - damage);
		if(getHealth() <= 0) {
			isAlive = false;
			ItemBlock item = new ItemBlock(Map.getItemIndexCounter(), getX(), getY(), 40, 40, "stone");
			Map.addItemByIndex(Map.getItemIndexCounter(), item);
			Map.setItemIndexCounter(Map.getItemIndexCounter() + 1);
		}
	}
	
	private boolean collidedWithBlock(int polX, int polY) {
		boolean cl = false;
		Block b = Map.getBlock(getX() + polX, getY() + polY);
		if(b != null) {
			cl = true;
		}
		
		b = Map.getBlock(getX() + getWidth() + polX, getY() + polY);
		if(b != null) {
			cl = true;
		}
		
		b = Map.getBlock(getX() + getWidth() + polX, getY() + getHeight() + polY);
		if(b != null) {
			cl = true;
		}
		
		b = Map.getBlock(getX() + polX, getY() + getHeight() + polY);
		if(b != null) {
			cl = true;
		}
		
		return cl;
	}

	@Override
	public void draw(GameContainer gc, Graphics g) {
		if(texture != null) {
			g.drawImage(texture, getX(), getY());
			g.setColor(Color.white);
			g.drawString(Integer.toString(getHealth()), getX(), getY());
		}
	}


	public Image getTexture() {
		return texture;
	}


	public void setTexture(Image texture) {
		this.texture = texture;
	}


	@Override
	public void update(GameContainer gc) throws SlickException {
		// TODO Auto-generated method stub
		
	}


	public boolean isAlive() {
		return isAlive;
	}


	public void setAlive(boolean isAlive) {
		this.isAlive = isAlive;
	}

}
